package JieKo;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
public class Test {
    public int a;

    @Override
    public boolean equals(Object o) {//父类那边与子类那边重写方法都是非静态的方法都是相同的，
        // 隐藏的形参this与传的形参都能安全或有转型地互传递过来，传参这边稳定
        if (this == o) return true;//只要是同一对象头的就给对了
        if (o == null || getClass() != o.getClass()) return false;
        Test test = (Test) o;//非静态方法都是自调传自，一定都有this，非静态方法里的this就是谁去调用它的谁就是，谁去调用它的this就是它
        return a == test.a;
    }

    @Override
    public int hashCode() {//以内容视对象相同了，相同的对象就要调到成一个对象，它们连锁重写的，
        // 两个对象通过equals方法比较是相等的，它们的hashCode必须相同
        return Objects.hash(a);//虽然默认实现可能与地址相关，但重写后的hashCode通常不再基于地址，而是基于对象的内部状态。
        // 例如，String类重写了hashCode，根据字符串的内容计算哈希码，这样相同内容的字符串即使不同实例也会有相同的哈希码。
        //基于对象内容计算分配并返回对象的哈希码
    }
    public static void main(String[] args) {
        Test test = new Test();
        Object o = new Test();//用来一键获取自己创的类的似复刻变量的全路径与地址，
        // 任何一个类都有已经提供好获取自身类创的似复刻变量路径加地址的toString方法的
        System.out.println(test.toString());//输出对象头那边的路径加地址
        System.out.println(o.toString());
        System.out.println("============");
        Test test2 = new Test();
        Object o2 = test2;//向上转型对象还是它，被隐藏的新的它，本质上有部分被隐藏下也还是它
        System.out.println(test2.toString());
        System.out.println(o2.toString());
        System.out.println("=================");
        Object o3 = new Object();
        System.out.println(o3.toString());
        System.out.println("=================");
        Test test3 = new Test();
        System.out.println(test3.equals(test3));//对象是对象，权限是权限，对象头地址都一样，不同类型给的权限不一样而已了，
        // 指向对象的引用的类型怎么变，对象永远都是在堆上的那一块不会变，==比较的是内存地址
    }

    public static void bubbleSort(Comparable[] comparable) {
        for (int i = 0; i < comparable.length-1; i++) {
            for (int j = 0; j < comparable.length-1-i; j++) {
                if(comparable[j].compareTo(comparable[j+1]) > 0) {
                    Comparable tmp = comparable[j];
                    comparable[j] = comparable[j+1];
                    comparable[j+1] = tmp;
                }
            }
        }
    }
    //引用类型数组都一样的，装的每个元素都是哈希值，对于数组来说里面每个哈希值权限怎样不管的，传指向数组的引用，
    //Comparable[j]里面都还是Student类的似复刻变量元素，它调用时直接调用子类自己这边重写的
}

class Student implements Comparable<Student> {//定义里面抽象方法形参的类型必须是Student，接口不能实例化，肯定是子类这边去调用的
    public int age;

    public Student(int age) {
        this.age = age;
    }

    @Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }

    public static void main(String[] args) {
        Student st = new Student(1);
        Comparable comparable1 = new Student(1);
        System.out.println(comparable1.compareTo(st));//comparable是向上转型来的，会转到st这个子类里的重写方法，并且转到时是子类权限全开了的
        System.out.println(comparable1.compareTo(comparable1));//comparable1参数传到子类方法Student o 来接时会向下转型
                                                               //向下转型在接口这边就发生了，向下转型后进来的调用传向下转型的到子类重写的方法
        Test test = new Test();
        comparable1.compareTo(test);//test是Test类型，向下转型时转不了的强转报错，父类接口这边是还没发现不能转的

        /*st.compareTo(test);//Comparable<Student>类型强制在了子类重写的这边，接口那边的形参其实还是Object类的类变量，
        // 所以类的父类任何类都能接收，连接了这个接口它里面是抽象方法子类这边一定有实现重写的，调用到重写传参时子类那边那个强制的类型接的对应的参数会去强转的
        st.compareTo(comparable1);//这边是因为直接调用子类这边的比较方法了，在子类这边是有类型强制的*/

        /*Comparable comparable2 = new Comparable();//接口是不能直接实例化的，与抽象类一样，对子类实例化间接实例化到（接口里还允许default修饰下的非静态方法）
        jieko jieko = new jieko();//接口抽象的肯定不能实例化的，实例化后去调用它里面抽象方法然后重写的肯定是从子类对象实例的，肯定是对应有子类重写方法的*/


    }
}
interface jieko {}


//比较的接口里面是不提供任何东西的抽象方法的，规则全由自己定的
//是接口就必须实现它里面的重写，这个克隆接口很特别，我们需要用的是接口里本身实现的那个本地方法的，而不是要用自己子类重写的，
// 子类这边出发，重写方法是两个相同的方法，要指定调用接口那边的用super指定调用它的克隆


class Test2 implements Cloneable {//克隆接口里面什么都没有的空接口，只是用来证明当前类可以被克隆的
    public int a = 20;

    //@Override
    /*protected Object clone() throws CloneNotSupportedException {//这边重写的方法是object父类里的clone方法
        return super.clone();*///重不重写看谁调用的这个父类的这个被重写的方法，
        // 这里的super特指调用是子类这边去调用的，如果是父类的似复刻变量去调用它里面的重写方法的才会重写
        //重写方法默认是实现调用父类被重写的方法，克隆这边就是要用接口那边的方法的
        //protected native Object clone() throws CloneNotSupportedException;
        // 本地实现的方法，返回Object类的似复刻变量，对谁克隆的里面统一返回后再各自强转向下转型回克隆对象的类型，
        // 克隆方法里对来的克隆出来的对象统一向上转型为object类来统一返回类型来返回，做到统一各自处理
        //方法object向上转型的返回后，要对它向下转型回来接

        //深浅拷贝就看拷贝时的实现，本地默认的能完成的是浅拷贝，
        // 要深拷贝的话重写这边改，实现多个浅拷贝混合在一起把引用有指的对象都拷贝一份，不止拷贝引用变量，对象都拷贝了后再修改一下拷贝的引用里的指向，指向拷贝的对象，实现深拷贝
        //}

    public static void main(String[] args) throws CloneNotSupportedException {
            Test2 test2 = new Test2();
            Test2 test21 = (Test2)test2.clone();//可以直接使用object父类里的clone方法的，即使它有protected修饰
            test21.a = 10;
        System.out.println(test2.a);
        System.out.println(test21.a);
        //到后面深拷贝的重写方法写好了两个方法子类直接调用clone就是调用子类重写的方法的
    }
}










class Test3 {
    public int a;
    String b;

    @Override
    public String toString() {
        return "Test3{" +
                "a=" + a +
                ", b='" + b + '\'' +
                '}';
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Test3 test3 = (Test3) o;
        return a == test3.a && Objects.equals(b, test3.b);
    }

    @Override
    public int hashCode() {
        return Objects.hash(a, b);
    }

    public static void main(String[] args) {
        Test3 test3 = new Test3();
        System.out.println(test3.toString());//Test.Test3@1b6d3586
        System.out.println(test3);//Test.Test3@1b6d3586
        Object object = new Object();
        Student student = new Student(10);
        /*test(student);*/ //err 直接不给转了
        /*Person person = student;*/ //err
        /*Person person = (Person) student;*/ //强转也不行


    }
    public static void test(Person person) {
    }
}










class Person implements Comparable<Person> /*extends AgeComparator*/ {
    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }
}
class AgeComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        return o1.age - o2.age;
    }
}
class Test1 {
    public static void main(String[] args) {
        Person[] peoples = new Person[3];
        peoples[0] = new Person("zhangsan",10);
        peoples[1] = new Person("zhangsan",10);
        peoples[2] = new Person("wangwu",20);
        Arrays.sort(peoples,new AgeComparator());
        System.out.println(Arrays.toString(peoples));
        System.out.println(peoples[0].hashCode());
        System.out.println(peoples[1].hashCode());
        System.out.println(peoples[2].hashCode());
        System.out.println(peoples[0] == peoples[1]);//==就是比较对象头地址
        System.out.println(peoples[0].equals(peoples[0]));
        System.out.println(peoples[0].equals(peoples[1]));
        System.out.println(peoples[0].equals(peoples[2]));
    }
}
class Money implements Cloneable {
    public double money = 19.9;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Person2 implements Cloneable {
    public int age;
    public Money money;//似复刻变量为非静态成员

    public Person2(int age) {
        this.age = age;
        this.money = new Money();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        /*return super.clone();*/
        Person2 tmp = (Person2) super.clone();//this一定是指向子类全权限的
        tmp.money = (Money) this.money.clone();
        return tmp;
    }

    @Override
    public String toString() {
        return "Person2{" +
                "age=" + age +
                ", money=" + money +
                '}';
    }
}
class Test4 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person2 person = new Person2(10);
        Person2 person2 = (Person2) person.clone();
        System.out.println(person.money.money);
        System.out.println(person2.money.money);
        person2.money.money = 99.99;
        System.out.println(person.money.money);
        System.out.println(person2.money.money);
    }
}

class OuterClass {
    class InnerClass {
        //实例内部类
    }
    static class InnerClass2 {
        //静态内部类
    }
}
interface A {
    void testA();
}
class B {//{}类变量B里的内容

}
class Test5 {
    public static void main(String[] args) {
        A a = new A() {//匿名内部类，似复刻变量，{}变量里的内容
            @Override
            public void testA() {
                System.out.println("hehe");
            }
        };
        new B() {

        };
        a.testA();
    }
}




